`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Westlake University
// Engineer: shenziyang@westlake.edu.cn
// 
// Create Date: 2021/11/20 21:01:30
// Design Name: HW2
// Module Name: BCD_dec_adder1bit
// Project Name: hw2
// Target Devices: VCU118
// Tool Versions: vivado 2020.1
// Description: Homework 2 for Fudan PLD & HDL courses
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module BCD_dec_adder1bit(
    input cin,                      //进位输入Cin
    input clk,                      //时钟clk
    input ena,                      //允许计数标志ena
    input rst_n,                    //reset信号,高电平有效
    output reg cout,                //进位输出Cout
    output reg D,                   //单bit输出从高位到低位：DCBA
    output reg C,                   //需要把输出output都定义成寄存器
    output reg B,
    output reg A
    );
    reg [3:0] result;               //result用来存储加法计数器的每次结果（数到哪儿了）
    integer i;                      //遍历标识符i
    initial begin                   //将result的结果初始化为0
        result <= 0;
    end
    always @(posedge clk or negedge rst_n) begin    //时钟上升沿触发
        if (rst_n) begin
            cout = 0;
            D = 0;
            C = 0;
            B = 0;
            A = 0;
        end
        else if(ena) begin
            if(cin) begin
                result = result + 1;   //进位，result+1
            end
            if(result == 8) begin
                cout = 1;
            end
            if(result >= 9) begin      //当result已经是9的时候
                result = 0;            //将result归置为0
                cout = 0;             //将进位输出设置为1
            end 
            else if(result < 9) begin  //不需要进位的情况
                result = result + 1;   //result每次+1，加法计数器
            end
            D = result[3];
            C = result[2];
            B = result[1];
            A = result[0];
        end
    end
endmodule

/*
如何解决输入进位信号到输出的传输：
输入只能是wire(net)类型，可以由wire(net)/reg类型驱动
输出可以是wire(net)/reg类型，只能由wire(net)类型驱动
    需要输入信号参与reg类型的计算时：
    创建一个输入信号的reg变量，将输入信号用作敏感信号，在敏感触发后将输入信号的值赋给reg变量[即，使用wire(net)类型驱动reg类型]
*/
/*
注意：加法计数器的进位逻辑中，当有进位输入，即cin有效时，result需要+1，同时在正常的计数器逻辑中，result也要+1
所以result需要使用阻塞赋值，否则cin中对result+1的变化无法被计数逻辑继承。
*/
/*
需要加入enable信号和reset信号：
enable信号的意义在于，当个位计数器数满之后，产生的进位信号才会使十位开始计数，此时需要使用enable信号拖慢十位计数的速度，个位每数十个数，十位数一次。
reset信号的意义在于在一开始的时候将所有的状态清零，从而能数到0。并且健全的计数器需要reset信号。
*/
/*
进位使能信号cout_mid落后了一拍如何处理？
现象：进位使能信号落后了一拍导致10，20...都数不到，数到的都是00，10...
解决方法：在数到8的时候就给出进位信号，提前一拍让下一级计数。
*/